/*
 * @Description:
 * @Author: dh
 * @Date: 2021-09-24 14:53:15
 * @LastEditors: dh
 * @LastEditTime: 2024-05-14 15:19:44
 */

// TODO 泛型接口
interface funcType<T> {
	(name: string, age: T, sex?: string): void
}
let func: funcType<number> = function (name, age, sex) {}

// 泛型函数
function fn<T>(age: T): T {
	return age
}

fn<number>(20) //常规写法
fn('20') //这里会根据入参类型反推age是string类型

// TODO 多参数的泛型类型
interface GenericType<T, U> {
	id: T
	name: U
}
function showType(args: GenericType<number, string>) {
	console.log(args)
}
showType({ id: 10, name: '123' })

// TODO 泛型约束  这里约束参数必须具有length属性
function getProperty<T extends { length: number }>(arg: T): number {
	return arg.length
}
getProperty('123')
// getProperty(123); // 不具有length属性 报错

// TODO 泛型 类型别名
type Cart<T> = T | T[]
let c1: Cart<string> = '1'
let c2: Cart<number> = [1]

// TODO 泛型 类
class Test<T> {
	value: T
	constructor(value: T) {
		this.value = value
	}
	add<T>(x: T) {
		return x
	}
}

let myTest = new Test<number>(123)
myTest.value = 0
myTest.add<number>(12)

// TODO keyof 约束泛型对象
function props<T, K extends keyof T>(obj: T, key: K): any {
	return obj[key]
}
const ob = { a: '1', b: 2 }
props(ob, 'a')
props(1, 'toFixed') // 最好也约束一下第一个参数，如下

function getValue<T extends object, k extends keyof T>(obj: T, key: k): any {
	return obj[key]
}
